package sk.velkavrana.app.ui.components;

import com.jgoodies.binding.adapter.BasicComponentFactory;
import com.jgoodies.binding.value.AbstractValueModel;
import com.jgoodies.binding.value.ValueModel;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * @author mtymes
 * @since May 24, 2009 11:31:44 PM
 */
public class JChooserPanel extends JPanel {

    private Set<String> values = new TreeSet<String>();

    private List<JCheckBox> checkBoxes = new ArrayList<JCheckBox>();


    private JPanel initContentPanel(final Set<String> options, final Set<String> selected) {
        StringBuilder rows = new StringBuilder();

        rows.append("2dlu, ");
        for (int i = 0; i < options.size(); i++) {
            rows.append("pref, ");
        }
        rows.append("2dlu");


        FormLayout contentLayout = new FormLayout(
                "4dlu, pref:grow, 4dlu", // columns
                rows.toString() // rows
        );

        JPanel contentPanel = new JPanel(contentLayout);

        CellConstraints cc = new CellConstraints();
        int i = 2;
        for (final String value : options) {

            if (selected != null && selected.contains(value)) {
                values.add(value);
            }

            ValueModel checkBoxModel = new AbstractValueModel() {
                public Object getValue() {
                    return values.contains(value);
                }


                public void setValue(Object o) {
                    if (Boolean.TRUE.equals(o)) {
                        values.add(value);
                    } else {
                        values.remove(value);
                    }
//                    System.out.println(values);
                }
            };

            JCheckBox checkBox = BasicComponentFactory.createCheckBox(checkBoxModel, value);

            contentPanel.add(checkBox, cc.xy(2, i++));
            checkBoxes.add(checkBox);
        }

        return contentPanel;
    }


    private JButton initAllButton() {
        JButton allButton = new JButton(new AbstractAction("All") {
            public void actionPerformed(ActionEvent e) {
                for (JCheckBox checkBox : checkBoxes) {
                    if (!checkBox.isSelected()) {
                        checkBox.setSelected(true);
                    }
                }
            }
        });

        allButton.setMnemonic(KeyEvent.VK_A);

        allButton.setBorder(BorderFactory.createEtchedBorder());

        return allButton;
    }


    private JButton initNoneButton() {
        JButton noneButton = new JButton(new AbstractAction("None") {
            public void actionPerformed(ActionEvent e) {
                for (JCheckBox checkBox : checkBoxes) {
                    if (checkBox.isSelected()) {
                        checkBox.setSelected(false);
                    }
                }
            }
        });

        noneButton.setMnemonic(KeyEvent.VK_N);

        noneButton.setBorder(BorderFactory.createEtchedBorder());

        return noneButton;
    }


    private JButton initInverseButton() {
        JButton inverseButton = new JButton(new AbstractAction(" Inverse ") {
            public void actionPerformed(ActionEvent e) {
                for (JCheckBox checkBox : checkBoxes) {
                    checkBox.setSelected(!checkBox.isSelected());
                }
            }
        });

        inverseButton.setMnemonic(KeyEvent.VK_I);

        inverseButton.setBorder(BorderFactory.createEtchedBorder());

        return inverseButton;
    }


    private JPanel initButtonPanel() {
        FormLayout buttonLayout = new FormLayout(
                "2dlu, pref, 4dlu, pref, 4dlu, pref, 2dlu", // columns
                "2dlu, pref, 2dlu" // rows
        );

        buttonLayout.setColumnGroups(new int[][]{{2, 4, 6}});

        JPanel buttonPanel = new JPanel(buttonLayout);
//        buttonPanel.setBorder(BorderFactory.createEtchedBorder());

        CellConstraints cc = new CellConstraints();
        buttonPanel.add(initAllButton(), cc.xy(2, 2));
        buttonPanel.add(initNoneButton(), cc.xy(4, 2));
        buttonPanel.add(initInverseButton(), cc.xy(6, 2));

        return buttonPanel;
    }


    private void init(final String title, final Set<String> options, final Set<String> selected) {

        FormLayout chooserLayout = new FormLayout(
                "2dlu, default:grow, 2dlu", // columns
                "0dlu, default:grow, 4dlu, pref, 2dlu" // rows
        );

        setLayout(chooserLayout);
        setBorder(BorderFactory.createTitledBorder(title));

        CellConstraints cc = new CellConstraints();
        JScrollPane scrollPane = new JScrollPane(initContentPanel(options, selected));
        scrollPane.setBorder(BorderFactory.createEtchedBorder());
        add(scrollPane, cc.xy(2, 2));
        add(initButtonPanel(), cc.xy(2, 4));

    }


    public JChooserPanel(LayoutManager layout, boolean isDoubleBuffered, final String title, final Set<String> options, final Set<String> selected) {
        super(layout, isDoubleBuffered);

        init(title, options, selected);
    }


    public JChooserPanel(LayoutManager layout, final String title, final Set<String> options, final Set<String> selected) {
        super(layout);

        init(title, options, selected);
    }


    public JChooserPanel(boolean isDoubleBuffered, final String title, final Set<String> options, final Set<String> selected) {
        super(isDoubleBuffered);

        init(title, options, selected);
    }


    public JChooserPanel(final String title, final Set<String> options, final Set<String> selected) {
        init(title, options, selected);
    }


    public Set<String> getValues() {
        return values;
    }
}
